<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas Text Rendering Character by Character</title>
    <style>
        canvas {
            border: 1px solid #000;
            z-index: 50; /* 确保这个值足够高，以覆盖其他内容 */
            position: absolute; /* 避免占用页面空间 */
        }

         /* 隐藏输入框，但保持其可接受输入 */
         #editableDiv {
        opacity: 0; /* 使div不可见但仍然可以接收输入 */
        position: absolute; /* 避免占用页面空间 */
        top: -100;
        left: -1000;
        width: 110px; /* 最小化可编辑区域的尺寸 */
        height: 10px; /* 最小化可编辑区域的尺寸 */
        overflow: hidden; /* 避免滚动条出现 */
    }

    #contextMenu {
            display: none;
            position: absolute;
            z-index: 1000; /* 确保这个值足够高，以覆盖其他内容 */
            background-color: white;
            border: 1px solid #ddd;
            padding: 10px;
            box-shadow: 3px 3px 5px rgba(0,0,0,0.2); /* 阴影效果 */
        }

        #contextMenu ul {
            list-style: none;
            margin: 0;
            padding: 0;
        }

        #contextMenu ul li {
            padding: 8px;
            cursor: pointer;
        }

        #contextMenu ul li:hover {
            background-color: #f7f7f7;
        }

        .button-container {
            text-align: center; /* 将按钮居中对齐 */
            margin-top: 10px; /* 在容器和画布之间添加一些空间 */
            position: absolute;
            z-index: 150; /* 确保这个值足够高，以覆盖其他内容 */
        }

    </style>



</head>
<body>
    <canvas id="canvas" width="800" height="300"></canvas>
     <!-- 看不见的输入框 -->
 
     <div id="editableDiv" contenteditable="true"></div>

     <div id="contextMenu">
        <ul>
            <li id="copy">复制</li>
            <li id="paste">粘贴</li>
        </ul>
    </div>


    <div class="button-container">
        <button id="fontSizeBtn">字体大小28</button><button id="fontSizeBtn2">字体大小50</button>
        <button id="fontColorBtn">字体颜色(红)</button>
        <button id="fontColorBtn2">字体颜色(蓝)</button>
    </div>


    <script>
           var textData = {
            text: "您好中国！",
            styles: [
                { start: 0, end: 2, font: "黑体", fontSize:40,color: "red" },
                { start: 2, end: 6, font: "楷体", fontSize:80,color: "green" }
            ]
        };

       document.addEventListener("DOMContentLoaded", function() {
       


        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
     
        let isSelecting = false;
        let selectionStart = null;
        let selectionEnd = null;
        const charWidths = [];
        let lineHeight = 0;        // 添加行高变量
        let cursorPosition = null; // 光标位置         
        let cursorVisible = false; // 控制光标显示的状态
        let hasSelection = false;  // 添加一个变量来跟踪选择状态
        let isComposing = false;

  

        
                


       
        const editableDiv = document.getElementById('editableDiv');
        let initialText = "";      // 记录开始输入时的文本
        let initialSelectionStart = 0; // 记录开始输入时的光标或选区开始位置
        let initialSelectionEnd = 0;   // 记录开始输入时的光标或选区结束位置
        let initialTextLength = 0;
		let initialCursorPosition = 0;
        
        editableDiv.style.width = '1px';
        editableDiv.style.height = '1px';
        editableDiv.style.opacity = 0;


        const contextMenu = document.getElementById('contextMenu');
        const copyMenuItem = document.getElementById('copy');
        const pasteMenuItem = document.getElementById('paste');

        const fontSizeBtn = document.getElementById('fontSizeBtn');
        const fontSizeBtn2 = document.getElementById('fontSizeBtn2');
        const fontColorBtn = document.getElementById('fontColorBtn');
        const fontColorBtn2 = document.getElementById('fontColorBtn2');

        fontSizeBtn.addEventListener('click', function() {
            console.log('C3 click TextSizeSet 28');
            updateSelectedTextSize(28);
            compressStyle();
           
            renderText();
        });

        fontSizeBtn2.addEventListener('click', function() {
            console.log('C3 click TextSizeSet 50');
            updateSelectedTextSize(50);
            compressStyle();
           
            renderText();
        });

        fontColorBtn.addEventListener('click', function() {
            updateSelectedTextColor('red');
            compressStyle();
            renderText();
        });

        fontColorBtn2.addEventListener('click', function() {
            updateSelectedTextColor('blue');
            compressStyle();
            renderText();
        });

        function updateSelectedTextSize(newSize) {

            console.log('C3 updateSelectedTextSize', newSize);
            const selectedText = textData.text.substring(selectionStart, selectionEnd);
            console.log("C3 选中文字",selectedText); // Print the selected text to the console

             // 保留新样式，可能会有多个新的样式分割而来
            let newStyles = [];
            var newFontSize=newSize;
            var index_next=0;

            // 遍历现有的样式
            textData.styles.forEach(style => {

                console.log('C3 index_next ',index_next);
                index_next++;

               

                if (style.end <= selectionStart || style.start >= selectionEnd) {
                    // 如果当前样式与选区没有重叠，保留这个样式
                   
                    
                  

                    newStyles.push(style);
                    console.log('C3 updateSelectedTextSize AA');
                } else {

                    console.log('C3 updateSelectedTextSize BB');

                    if(style.start==selectionStart&&style.end==selectionEnd)// 选区被当前样式完全包含
                    {
                        console.log('C3 选区被当前样式完全包含 cc');
                        newStyles.push({
                            start: style.start,
                            end: selectionStart,
                            fontSize: newFontSize,
                            font: style.font,
                            color: style.color
                        });

                    }
                    // 如果当前样式与选区有部分重叠
                    if (style.start < selectionStart) {
                        console.log('C3 updateSelectedTextSize dd');
                        // 如果样式开始于选区之前，需要分割这个样式
                        newStyles.push({
                            start: style.start,
                            end: selectionStart,
                            fontSize: style.fontSize,
                            font: style.font,
                            color: style.color
                        });
                    }

                    // 更新选区中的样式
                    newStyles.push({
                        start: Math.max(style.start, selectionStart),
                        end: Math.min(style.end, selectionEnd),
                        fontSize: newFontSize,
                        font: style.font,
                        color: style.color
                    });

                    if (style.end > selectionEnd) {
                        // 如果样式延续到选区之后，需要分割这个样式
                        newStyles.push({
                            start: selectionEnd,
                            end: style.end,
                            fontSize: newFontSize,
                            font: style.font,
                            color: style.color
                        });
                    }
                }
            });

            // 处理完全不重叠，即选区中的新文本样式
            if (!newStyles.some(style => style.start <= selectionStart && style.end >= selectionEnd)) {
                newStyles.push({
                    start: selectionStart,
                    end: selectionEnd,
                    fontSize: 40,
                    font: "Arial", // 如果有默认字体可以替换
                    color: "black" // 如果有默认颜色可以替换
                });
            }

            // 将新的样式数组赋值给 textData.styles
            textData.styles = newStyles;
           
            // textData.styles.forEach(style => {
            //     // 检查样式是否与选区有重叠
            //     //selectionStart, selectionEnd
            //     if (style.end >= selectionStart && style.start < selectionEnd) {
            //         // 计算重叠区域，只更新重叠区域的字体大小
            //         const overlapStart = Math.max(style.start, selectionStart);
            //         const overlapEnd = Math.min(style.end, selectionEnd);

            //         // 更新选中范围内的字体大小
            //         if(newSize=="90")
            //         style.fontSize = style.fontSize+5;
            //         else
            //         style.fontSize = style.fontSize-5;

            //         // 如果需要，可以进一步细化处理，比如当选区只覆盖样式区间的一部分时，可能需要分割样式区间
            //         // 以下代码暂时省略了这种情况的处理逻辑
            //     }
            // });
           
        }

        function updateSelectedTextColor(newColor) {
           // 新的样式数组
                let newStyles = [];

            // 遍历现有样式
            textData.styles.forEach(style => {
                if (style.end <= selectionStart || style.start >= selectionEnd) {
                    // 当前样式与选区无重叠，保留此样式
                    newStyles.push(style);
                } else {
                    // 样式与选区有部分重叠
                    if (style.start < selectionStart) {
                        // 样式开始于选区之前，分割此样式
                        newStyles.push({
                            start: style.start,
                            end: selectionStart,
                            font: style.font,
                            fontSize: style.fontSize,
                            color: style.color
                        });
                    }

                    // 更新选区内的样式颜色
                    newStyles.push({
                        start: Math.max(style.start, selectionStart),
                        end: Math.min(style.end, selectionEnd),
                        font: style.font,
                        fontSize: style.fontSize,
                        color: newColor
                    });

                    if (style.end > selectionEnd) {
                        // 样式延续到选区之后，分割此样式
                        newStyles.push({
                            start: selectionEnd,
                            end: style.end,
                            font: style.font,
                            fontSize: style.fontSize,
                            color: style.color
                        });
                    }
                }
            });

            // 处理选区中新文本的样式，若完全不重叠
            if (!newStyles.some(style => style.start <= selectionStart && style.end >= selectionEnd)) {
                newStyles.push({
                    start: selectionStart,
                    end: selectionEnd,
                    font: "Arial", // 使用默认字体
                    fontSize: 16, // 使用默认字体大小
                    color: newColor // 新颜色
                });
            }

            // 更新textData.styles为新的样式数组
            textData.styles = newStyles;
        }

        function compressStyle() {
            if (textData.styles.length === 0) return;

            // 首先，根据样式段的开始位置进行排序，确保样式按顺序处理
            textData.styles.sort((a, b) => a.start - b.start);

            let compressedStyles = [textData.styles[0]];

            for (let i = 1; i < textData.styles.length; i++) {
                let lastStyle = compressedStyles[compressedStyles.length - 1];
                let currentStyle = textData.styles[i];

                // 检查当前样式是否与上一个样式相同（字体、字号、颜色）
                if (lastStyle.font === currentStyle.font &&
                    lastStyle.fontSize === currentStyle.fontSize &&
                    lastStyle.color === currentStyle.color &&
                    lastStyle.end === currentStyle.start) {
                    // 如果当前样式与上一个样式完全相同，则合并这两个样式段
                    lastStyle.end = currentStyle.end;
                } else {
                    compressedStyles.push(currentStyle);
                }
            }

            // 更新textData的styles为压缩后的样式数组
            textData.styles = compressedStyles;

           
        }


        canvas.addEventListener('contextmenu', (e) => {
            e.preventDefault(); // 阻止默认的右键菜单

            const rect = canvas.getBoundingClientRect(); // 获取canvas的边界
            const menuWidth = contextMenu.offsetWidth;
            const menuHeight = contextMenu.offsetHeight;

            // 计算菜单的最佳位置，确保它不会超出canvas边界
            let x = e.clientX - rect.left; // 转换为相对于canvas的位置
            let y = e.clientY - rect.top;

            console.log(x, y);
            // 如果菜单超出右侧
            if (x + menuWidth > canvas.width) {
                x = canvas.width - menuWidth;
            }
            // 如果菜单超出底部
            if (y + menuHeight > canvas.height) {
                y = canvas.height - menuHeight;
            }

            // 设置自定义菜单的位置并显示
            contextMenu.style.top = `{y}px`;
            contextMenu.style.left = `{x}px`;
            contextMenu.style.display = 'block';
        });


        // 点击复制
        copyMenuItem.addEventListener('click', () => {
            copyToClipboard();  // 前面定义的复制函数
            contextMenu.style.display = 'none';  // 隐藏菜单
        });

        // 点击粘贴
        pasteMenuItem.addEventListener('click', () => {
            // 粘贴内容到画布并更新textData.text
            navigator.clipboard.readText().then((text) => {
                // 假设我们粘贴到光标当前位置
                insertTextAtCursor(text);
                renderText();  // 重新渲染画布
            });
            contextMenu.style.display = 'none';  // 隐藏菜单
        });

        // 点击其他地方时隐藏菜单
        document.addEventListener('click', (e) => {
            if (e.target !== contextMenu) {
                contextMenu.style.display = 'none';
            }
        });
   

    function insertTextAtCursor(text) {
        // 粘贴时的文本插入逻辑
        const beforeCursor = textData.text.slice(0, cursorPosition);
        const afterCursor = textData.text.slice(cursorPosition);
        textData.text = beforeCursor + text + afterCursor;
        cursorPosition += text.length;  // 更新光标位置
        // 需要更新样式信息（省略）
    }



     	 canvas.addEventListener('click', function() {
        editableDiv.focus(); // 当画布被点击时，设置焦点到editableDiv
    	});

        // 根据需要添加更多事件监听器，如compositionstart, compositionupdate

        // 开始输入复合字符（如中文字符）
        editableDiv.addEventListener('compositionstart', function(e) {
            isComposing = true;
            console.log('开始输入  =================================');
            initialText = textData.text;
            initialSelectionStart = selectionStart; // 假设你已经有这些值
            initialSelectionEnd = selectionEnd;
                        
        
        });

        // 输入复合字符过程中（可选，如果你需要实时获取输入法中的文本，可以使用此事件）
        editableDiv.addEventListener('compositionupdate', function(e) {
            // e.data 包含当前输入法组合中的文本
            console.log('输入更新  	:', e.data);
            clearSelection();
        });


        editableDiv.addEventListener('compositionend', function(e) {
            console.log(e.data); // 打印输入的文字
            // 更新canvas的文本内容
            isComposing = false;
                // // e.data 包含完成输入的复合字符
                // // 在这里插入字符到文本中
                const beforeCursor = textData.text.slice(0, cursorPosition);
                const afterCursor = textData.text.slice(cursorPosition);
                textData.text = beforeCursor + e.data + afterCursor;
                updateStylesForInsert(cursorPosition,e.data.length);
                cursorPosition += e.data.length; // 更新光标位置，这里假设插入文本的长度就是e.data的长度
                console.log('C1 输入完成	:', e.data," 字符串长",e.data.length);

               
                electionStart = null;
                selectionEnd = null;
            
                cursorVisible = true; // 可选：同时隐藏光标             

                renderText(); // 重新渲染文本和样式
        });

        // 确保editableDiv可以接收输入
       
        editableDiv.addEventListener('paste', function(e) {
            e.preventDefault(); // 阻止默认粘贴行为

            // 获取剪贴板中的文本内容
            const pasteText = e.clipboardData.getData('text');
            hasPastAction=true;
            console.log("内存粘贴开始:",pasteText);
            // 假定cursorPosition是当前光标在textData.text中的位置
            if (cursorPosition === null) {
                cursorPosition = textData.text.length; // 如果没有指定光标位置，则默认为文本末尾
            }

            // 将文本插入到光标位置
            const beforeCursor = textData.text.slice(0, cursorPosition);
            const afterCursor = textData.text.slice(cursorPosition);
            textData.text = beforeCursor + pasteText + afterCursor;

          

            // 更新样式（这个示例没有改变样式，但你可能需要根据插入的文本更新样式）
            updateStylesForInsert(cursorPosition, pasteText.length);

              // 更新光标位置
              cursorPosition += pasteText.length;

            // 重新渲染文本
            renderText();
        });
        var hasPastAction=false;

        function copyToClipboard() {
                if (selectionStart === null || selectionEnd === null || selectionStart === selectionEnd) {
                    console.log("没有选中的文本可以复制");
                    return;
                }
               

                // 提取选中的文本
                const selectedText = textData.text.slice(selectionStart, selectionEnd);

                // 创建一个临时的textarea元素用于复制操作
                const textarea = document.createElement('textarea');
                textarea.value = selectedText;
                document.body.appendChild(textarea);

                // 选中文本并复制
                textarea.select();
                document.execCommand('copy');

                // 移除临时创建的textarea
                document.body.removeChild(textarea);

                console.log("已复制到剪贴板: " + selectedText);
        }



   

            function insertTextAtPosition(text, position) {
                // 插入文本并更新textData.text
                const beforeText = textData.text.substring(0, position);
                const afterText = textData.text.substring(position);
                textData.text = beforeText + text + afterText;

                // 更新样式范围
                updateStylesForInsert(position, text.length);

                // 重新渲染文本（这取决于你的渲染逻辑）
                renderText();
            }

        // 调整原有的keydown事件监听器，只在非组合输入时处理
        document.addEventListener('keydown', function(e) {
            if (!isComposing && e.key.length === 1) {
                // 处理英文输入等非复合字符输入
            }
            // 其他按键处理，比如Backspace, Delete等
        });


        function isInSelection(x) {
                if (selectionStart === null || selectionEnd === null) return false;
                const startX = charWidths[selectionStart] ? charWidths[selectionStart].x : 0;
                const endX = charWidths[selectionEnd - 1] ? charWidths[selectionEnd - 1].x + charWidths[selectionEnd - 1].width : startX;
                return x >= startX && x <= endX;
            }

            function renderText() {
                let cursorX = 0;
                const cursorY = 100; // Y坐标位置
                ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除之前的渲染

                // 遍历文本之前计算选中文本的最大字体高度
                let maxHeight = 0; 
                if (selectionStart !== null && selectionEnd !== null) {
                    for (let i = selectionStart; i < selectionEnd; i++) {
                        const style = textData.styles.find(s => i >= s.start && i < s.end) || {fontSize: 16, font: "Arial"};
                        maxHeight = Math.max(maxHeight, style.fontSize);
                    }
                    highlightSelection(cursorY - maxHeight, maxHeight + 10); // 调整矩形框高度
                }

                // 逐个字输出
                for (let i = 0; i < textData.text.length; i++) {
                    const char = textData.text[i];
                    // 如果不存在样式，则使用默认样式
                    const style = textData.styles.find(s => i >= s.start && i < s.end) || {fontSize: 16, font: "Arial", color: "black"};
                    ctx.font = `${style.fontSize}px ${style.font}`; // 组合字体样式字符串
                    ctx.fillStyle = style.color;

                    const metrics = ctx.measureText(char);
                    ctx.fillText(char, cursorX, cursorY);
                    charWidths[i] = { width: metrics.width, x: cursorX };
                    cursorX += metrics.width;
                }

                if (cursorPosition !== null && cursorVisible) {
                    console.log("C2 准备绘制光标字体位置:", cursorPosition);
                    drawCursor(cursorPosition);
                }
            }

    //    function renderText() {
    //             let cursorX = 0;
    //             const cursorY = 100; // Y坐标位置
    //             ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除之前的渲染

    //             // 遍历文本之前计算选中文本的最大字体高度
    //             let maxHeight = 0; 
    //             if (selectionStart !== null && selectionEnd !== null) {
    //                 for (let i = selectionStart; i < selectionEnd; i++) {
    //                     const style = textData.styles.find(s => i >= s.start && i < s.end) || {font: "16px Arial"};
    //                     const fontSize = parseInt(style.font, 10); // 解析字体大小
    //                     maxHeight = Math.max(maxHeight, fontSize);
    //                 }
    //                 highlightSelection(cursorY - maxHeight, maxHeight + 10); // 调整矩形框高度
    //             }
	// 			//逐个字输出
    //             for (let i = 0; i < textData.text.length; i++) {
    //                 const char = textData.text[i];
    //                 //如果不存在样式，则使用默认样式
    //                 const style = textData.styles.find(s => i >= s.start && i < s.end) || {font: "16px Arial", color: "black"};
    //                 ctx.font = style.font;
    //                 ctx.fillStyle = style.color;

    //                 const metrics = ctx.measureText(char);
    //                 ctx.fillText(char, cursorX, cursorY);
    //                 charWidths[i] = { width: metrics.width, x: cursorX };
    //                 cursorX += metrics.width;
    //             }

    //             if (cursorPosition !== null && cursorVisible) {
    //                 console.log("C2 准备绘制光标字体位置  :",cursorPosition);
    //                 drawCursor(cursorPosition);
    //             }
    //         }

        function highlightSelection(cursorY, lineHeight) {
            if (selectionStart === null || selectionEnd === null) return;
            const start = charWidths[selectionStart] ? charWidths[selectionStart].x : 0;
            const end = charWidths[selectionEnd - 1] ? charWidths[selectionEnd - 1].x + charWidths[selectionEnd - 1].width : start;
            
            ctx.fillStyle = 'rgba(173, 216, 230, 0.5)'; // 浅蓝色半透明
            ctx.fillRect(start, cursorY, end - start, lineHeight); // 绘制矩形高亮选中区域
        }

        function drawCursor(position) {
            if (position === null || position < 0 || position >= textData.text.length+1) return;
            var totalWidth=0;
            var chartCount=0;

            charWidths.forEach(objectOfChar => {
                console.log('width: '+objectOfChar.width + ' x:' + objectOfChar.x);
                totalWidth+=objectOfChar.width;
                chartCount++;
            
            });
            if(position>chartCount)
            position=chartCount


            console.log("C2 开始绘制光标字体位置入参  :",position+" 字符个数: " + chartCount	);
            var cursorX = (charWidths[position] ? charWidths[position].x : 0) + 2; // 给光标一个小偏移
            const cursorHeight = 20; // 假定光标高度
            const cursorY = 100 - cursorHeight; // 基于文本绘制基线调整光标位置

            if(position>=chartCount)
            {
                cursorX=totalWidth;
                console.log("C2 : 光标位置超过字体宽度  :",position+"  字数:"+chartCount);
            }

            ctx.beginPath();
            ctx.moveTo(cursorX, cursorY);
            ctx.lineTo(cursorX, cursorY + cursorHeight);
            ctx.strokeStyle = 'black';
            ctx.lineWidth = 2;
            ctx.stroke();
        }



        function clearSelection() {
                // 重置选择状态
                selectionStart = null;
                selectionEnd = null;
                // 如果需要在取消选择时也隐藏光标，取消以下注释
                // cursorPosition = null;
                // cursorVisible = false; // 可选：同时隐藏光标

                // 重新渲染画布以更新显示状态
                renderText();
            }

        
        function blinkCursor() {
                cursorVisible = !cursorVisible;
                renderText();
            }

            setInterval(blinkCursor, 500); // 设置光标闪烁的间隔

            // 事件处理函数与之前相同，但需要更新以管理光标位置和可见性


        function getCharIndex(x) {
            for (let i = 0; i < charWidths.length; i++) {
                const { width, x: charX } = charWidths[i];
                if (x >= charX && x <= charX + width) {
                    return i;
                }
            }
            return null;
        }
        //用坐标返回当前字符内容
        function getCharByIndex(position) {
            if (position === null || position < 0 || position >= textData.text.length) return;

            for (let i = 0; i < textData.text.length; i++) {
                    const char = textData.text[i];
                    const style = textData.styles.find(s => i >= s.start && i < s.end) || {font: "16px Arial", color: "black"};
                    ctx.font = style.font;
                    ctx.fillStyle = style.color;
                    if(i===position)
                    {
	                       return char;
                    }
                   

                 
                }

           
        }


        function updateCursorPosition(x) {
            const rect = canvas.getBoundingClientRect();
            const clickX = x - rect.left; // 获取相对于canvas的点击位置
            cursorPosition = getCharIndex(clickX);
            cursorVisible = true; // 显示光标
        }

        function updateStylesForInsert(insertPosition, insertLength) {
            var isFind=false;
            console.log("C3 -> 更新样式！：",insertPosition);
            const selectedText = textData.text.substring(selectionStart, selectionEnd);
                    console.log("C3 选中文字",selectedText); // Print the selected text to the console

            var tempIndex=0;
                textData.styles.forEach(style => {

                    console.log("C1 -> forEach 更新样式！：",insertPosition," tempIndex:" ,tempIndex);
                    tempIndex++;
                    if(isFind==false)
                    {
                        // 如果插入位置在当前样式范围之前，或恰好在其开始位置
                        if (insertPosition==0) 
                        {
                           
                        	style.start =0;
                        	style.end += insertLength;
                            isFind=true;
                            console.log("C1 ->",insertPosition," 在当前样式之前  style.start="+insertPosition);
                            //当字符输入完成之后insertPosition会自增 ，要注意这个现象 。。
                        }
                        else
                        {  //插入位置在当前样式范围之间结束位置+1
                            if (insertPosition> style.start&&insertPosition <style.end)  
                            {
                                console.log("C1 -> ",insertPosition," 在当前样式之间");
                                style.end += insertLength;
                                isFind=true;
                            }else
                            {
                                if(insertPosition===style.end)
                                {
                                    console.log("C1 ->",insertPosition," 在当前样式最后尾");
                                    style.end += insertLength;
                                    isFind=true;
                                }

                            }

                           
                        }
                      
                        

                    }                    
                     else {
                        // 如果插入位置在当前样式范围内部，只需要调整结束位置
                        style.start += insertLength;
                        style.end += insertLength;
                    }
                    
                });
            }

        canvas.addEventListener('mousedown', function(e) {
                const rect = canvas.getBoundingClientRect();
                const x = e.clientX - rect.left;
                const charIndex = getCharIndex(x);
                console.log("点击鼠标下所在字符的序号 ：：",charIndex);

                var selectChar=getCharByIndex(charIndex);

                console.log("点击鼠标下所在字符是 ：：",selectChar)
               

                
                
                if (isInSelection(x)) {
                    // Clicked inside selection, do nothing to keep the selection
                    cursorVisible = true; // 可选：同时隐藏光标
                } else if (charIndex !== null) {
                    isSelecting = true;
                    selectionStart = charIndex;
                    selectionEnd = charIndex + 1;
                } else {
                                 
                   
                    clearSelection(); // 如果点击非文本区域，则取消选择
  
                    /////////////
                }

                if (hasSelection) {
                    clearSelection(); // 如果已有选择，首先清除
                    hasSelection = false; // 重置选择状态
                }

                // 每次mousedown时重置选择状态，但保存光标位置
                isSelecting = true;
                updateCursorPosition(e.clientX);

               
               

                renderText(); // 重新渲染更新画布状态
            });


        canvas.addEventListener('mousemove', function(e) {
      
            if (isSelecting) {
                // 如果在选择过程中移动鼠标，更新选择区域
                const rect = canvas.getBoundingClientRect();
                const x = e.clientX - rect.left;
                const charIndex = getCharIndex(x);
                if (charIndex !== cursorPosition) {
                    selectionStart = Math.min(cursorPosition, charIndex);
                    selectionEnd = Math.max(cursorPosition, charIndex) + 1;
                    renderText();
                }
            }
        });

        canvas.addEventListener('mouseup', function(e) {
            if (isSelecting && selectionStart !== null && selectionEnd !== null && selectionStart !== selectionEnd) {
                    // 如果完成了选择，则保留选择区域
                    cursorVisible = false; // 可以选择隐藏光标
                } else {
                    // 如果没有移动鼠标，则仅显示光标
                    updateCursorPosition(e.clientX);
                }
                isSelecting = false; // 重置选择状态
                renderText(); // 重新渲染以应用最终状态

        });

        canvas.addEventListener('dblclick', function(e) {
                const rect = canvas.getBoundingClientRect();
                const x = e.clientX - rect.left;
                if (isInSelection(x)) {
                    // Double clicked inside selection
                    const selectedText = textData.text.substring(selectionStart, selectionEnd);
                    console.log(selectedText); // Print the selected text to the console
                }
            });

            function updateStylesForDelete(position, length) {
                console.log("updateStylesForDelete");
                textData.styles.forEach(style => {
                    if (position < style.start) {
                        style.start -= length;
                        style.end -= length;
                    } else if (position < style.end) {
                        style.end -= length;
                    }

                    // 防止start和end反转
                    if (style.start > style.end) {
                        style.start = style.end;
                    }
                });
            }


            document.addEventListener('keydown', function(e) {
                
                
                  // 检测是否同时按下了Ctrl键和C键
                  if (e.ctrlKey && e.key === 'c') 
                {
                    // 调用复制到剪贴板的函数
                    copyToClipboard();

                    e.preventDefault(); // 防止默认的复制行为
                }
             
                   // 检测是否同时按下了Ctrl键和v键
                   if (e.ctrlKey && e.key === 'v') 
                {
                   
                  return;
                }
             

                // 确保不是控制键，比如箭头键、Backspace等
                if (e.key.length === 1) {
                    // 在这里插入字符到textData.text
                    const beforeCursor = textData.text.slice(0, cursorPosition);
                    const afterCursor = textData.text.slice(cursorPosition);
                    console.log("英文输入 前：：",textData.text);

                    
                
                    textData.text = beforeCursor + e.key + afterCursor;
                    //在这里要调整输入字母的样式 ，增加了一个

                    console.log("英文输入后 ：：",textData.text," 插入位置  ",cursorPosition);
                    
                    updateStylesForInsert(cursorPosition,1);
                    electionStart = null;
                    selectionEnd = null;
                    // 如果需要在取消选择时也隐藏光标，取消以下注释
                    // cursorPosition = null;
                       cursorVisible = true; // 可选：同时隐藏光标
                        // 更新光标位置
                    cursorPosition++;

                    renderText(); // 重新渲染文本
                }

                if (e.key === 'Backspace' && cursorPosition > 0) {
                    const beforeCursor = textData.text.slice(0, cursorPosition - 1);
                    const afterCursor = textData.text.slice(cursorPosition);
                    textData.text = beforeCursor + afterCursor;
                    electionStart = null;
                    selectionEnd = null;

                    cursorPosition--;

                    renderText();
                } 
                else if (e.key === 'Delete' && cursorPosition < textData.text.length) {
                    const beforeCursor = textData.text.slice(0, cursorPosition);
                    const afterCursor = textData.text.slice(cursorPosition + 1);
                    textData.text = beforeCursor + afterCursor;

                    // 光标位置不变
                    electionStart = null;
                    selectionEnd = null;

                    renderText();
                }

                if (e.key === 'ArrowLeft' && cursorPosition > 0) {
                    cursorPosition--;
                    console.log("《《光标位置移动",cursorPosition);
                    electionStart = null;
                    selectionEnd = null;
                    
                    renderText();
                } 
                else if (e.key === 'ArrowRight' && cursorPosition <= textData.text.length) {
                    cursorPosition++;
                    console.log("光标位置移动=》》",cursorPosition);
                    var chartCount=0;

                    charWidths.forEach(objectOfChar => {
                        console.log('width: '+objectOfChar.width + ' x:' + objectOfChar.x);
                      
                        chartCount++;
                        

                    });

                    if(cursorPosition>chartCount)
                    cursorPosition=chartCount;
                    electionStart = null;
                    selectionEnd = null;

                    renderText();
                }

               

        renderText();
    });


});

    </script>
</body>
</html>
